﻿using SqlSugar;
using SugarRedis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Zhaoxi.SqlSugar.Common;
using Zhaoxi.SqlSugar.Models;
using static Google.Protobuf.Reflection.SourceCodeInfo.Types;
using static Org.BouncyCastle.Math.EC.ECCurve;

namespace Zhaoxi.SqlSugarAdvanced
{
    public class L2Cache
    {
        /// <summary>
        /// 二级缓存 - 一些全局通用的配置表可以使用缓存
        /// </summary>
        public static void Show()
        {
            //ICacheService myCache = new SqlSugarRedisCache();//这个类如何建看标题5 
            ConnectionConfig connectionConfig = new ConnectionConfig()
            {
                ConnectionString = CustomConnectionConfig.ConnectionString001,
                DbType = DbType.SqlServer,
                IsAutoCloseConnection = true,
                ConfigureExternalServices = new ConfigureExternalServices() // 配置二级缓存
                {
                    DataInfoCacheService = new SqlSugarRedisCache() // 配置二级缓存实例
                }
            };

            using (SqlSugarClient db = new SqlSugarClient(connectionConfig))
            {
                db.Aop.OnLogExecuting = (sql, para) => { // 输出sql语句
                    Console.WriteLine($"Sql语句：{sql}");
                };
                if (db.DbMaintenance.IsAnyTable("Company", false))
                {
                    db.DbMaintenance.DropTable<Company>(); // 删除表
                }
                db.CodeFirst.InitTables<Company>(); // 创建表
               
                Company company = new Company()
                {
                    CompanyName = "朝夕教育",
                    CreateTime = DateTime.Now
                };
                db.Insertable<Company>(company).ExecuteCommand(); // 插入数据

                Company updateCompany = db.Queryable<Company>()
                   .Where(it => it.Id == 1).First();

                #region 语句1 - 设置缓存默认一天 
                //语句1 - 设置缓存默认一天 
                {
                    ////设置缓存默认一天 
                    //Company company1 = db.Queryable<Company>()
                    //    .Where(it => it.Id == 1)
                    //    .WithCache().First();  //查询结果后，会把数据保存到缓存中去
                    //Console.WriteLine($"第一次查询到的数据,数据做缓存：{company1.CompanyName}");
                    //Task.Run(() =>
                    //{
                    //    while (true)
                    //    {
                    //        Company companies1 = db.Queryable<Company>().Where(it => it.Id == 1)
                    //        .WithCache().First();
                    //        Console.WriteLine($"查询到的缓存数据：{companies1.CompanyName}");
                    //        Thread.Sleep(2000);
                    //    }
                    //});
                    ////现在开始修改数据库数据
                    //updateCompany.CompanyName = "修改数据---朝夕教育";
                    //db.Updateable<Company>(updateCompany).ExecuteCommand();
                    //Console.Read();
                }
                #endregion

                #region 语句2 - 设置指定缓存时间
                //语句2 - 设置指定缓存时间
                {
                    //Console.WriteLine("验证缓存的过期时间~~");
                    //List<Company> companies2 = db.Queryable<Company>()
                    //    .Where(it => it.Id == 1)
                    //    .WithCache(5) //设置具体过期时间
                    //    .ToList();

                    //Console.WriteLine($"第一次查询到的数据,数据做缓存：{Newtonsoft.Json.JsonConvert.SerializeObject(companies2)}");
                    //Task.Run(() =>
                    //{
                    //    while (true)
                    //    {
                    //        Console.WriteLine("缓存后马上开始查询数据~~");
                    //        List<Company> companies1 = db.Queryable<Company>().Where(it => it.Id == 1).ToList();
                    //        Console.WriteLine($"查询到的缓存数据：{Newtonsoft.Json.JsonConvert.SerializeObject(companies1)}");
                    //        Thread.Sleep(7000);

                    //        Console.WriteLine("7秒时间过后，再查询数据~~");
                    //        List<Company> companies2 = db.Queryable<Company>().Where(it => it.Id == 1).ToList();
                    //        Console.WriteLine($"7秒时间过后，查询到的缓存数据：{Newtonsoft.Json.JsonConvert.SerializeObject(companies2)}");
                    //    }
                    //});
                    ////现在开始修改数据库数据
                    //updateCompany.CompanyName = "修改数据---朝夕教育";
                    //db.Updateable<Company>(updateCompany).ExecuteCommand();
                    //Console.Read();
                }
                #endregion

                //语句3
                {
                    //bool isCache = true;
                    //List<Company> list = db.Queryable<Company>()
                    //             .WithCacheIF(isCache, 2000)
                    //             .ToList();
                }

                //语句4.半自动清空缓存 ：
                //当Company表发生删除操作，并且删除操作用了RemoveDataCache，那么查询语句1、语句2和语句3 都会清空缓存 
                //只支持实体
                //插入和更新一样用法
                {

                    //Console.WriteLine("第一次查询");
                    //Company company1 = db.Queryable<Company>()
                    //   .Where(it => it.Id == 1)
                    //   .WithCache(5) //设置具体过期时间
                    //   .First();

                    //Console.WriteLine("第二次查询");
                    ////查询的是缓存的数据
                    //Company companyNew = db.Queryable<Company>()
                    //   .Where(it => it.Id == 1)
                    //   .WithCache(5) //设置具体过期时间
                    //   .First();
                     
                    //db.Deleteable<Company>().Where(it => it.Id == 1)
                    //    .RemoveDataCache().ExecuteCommand();
                    //Company company3 = db.Queryable<Company>()
                    // .Where(it => it.Id == 1)
                    // .WithCache(5) //设置具体过期时间
                    // .First();
                }


                ////2.全自动清理：
                ////所有 增、删 、改 会自动调用.RemoveDataCache()
                //ConnectionConfig config = new ConnectionConfig()
                //{
                //    ConnectionString = CustomConnectionConfig.ConnectionString001,
                //    IsAutoCloseConnection = true,
                //    MoreSettings = new ConnMoreSettings()
                //    {
                //        IsAutoRemoveDataCache = true
                //    }
                //};
                ////缺点：
                ////基本单表查询和联表查询都支持，如果用到子查询或者Mergetable就无法自动清除了，这种情况用 【4.2追加key模式】

                ////3.根据Key关键词清空
                //db.DataCache.RemoveDataCache("MyCackey"); //比如缓存KEY带有MyCackey关键词的全部清空


            }
        }
    }

    /// <summary>
    /// 可以直接使用的-通用的二级缓存类
    /// </summary>
    public class SqlSugarRedisCache : ICacheService
    {

        //NUGET安装 SugarRedis  （也可以自个实现）   
        //注意:SugarRedis 不要扔到构造函数里面， 一定要单例模式  
        public static SugarRedisClient _service = new SugarRedisClient("127.0.0.1:6379,password=,connectTimeout=3000,connectRetry=1,syncTimeout=10000,DefaultDatabase=0");


        //+1重载 new SugarRedisClient(字符串)
        //默认:127.0.0.1:6379,password=,connectTimeout=3000,connectRetry=1,syncTimeout=10000,DefaultDatabase=0
        /// <summary>
        /// 添加
        /// </summary>
        /// <typeparam name="V"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void Add<V>(string key, V value)
        {
            _service.Set(key, value);
        }

        /// <summary>
        /// 过期时间的保存数据
        /// </summary>
        /// <typeparam name="V"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="cacheDurationInSeconds"></param>
        public void Add<V>(string key, V value, int cacheDurationInSeconds)
        {
            _service.Set(key, value, cacheDurationInSeconds);
        }

        /// <summary>
        /// 判断是否存在
        /// </summary>
        /// <typeparam name="V"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool ContainsKey<V>(string key)
        {
            return _service.Exists(key);
        }

        /// <summary>
        /// 获取缓存数据
        /// </summary>
        /// <typeparam name="V"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public V Get<V>(string key)
        {
            return _service.Get<V>(key);
        }

        /// <summary>
        /// 获取缓存key
        /// </summary>
        /// <typeparam name="V"></typeparam>
        /// <returns></returns>
        public IEnumerable<string> GetAllKey<V>()
        {
             
            return _service.SearchCacheRegex("SqlSugarDataCache.*");
        }

        /// <summary>
        /// 获取或创建
        /// </summary>
        /// <typeparam name="V"></typeparam>
        /// <param name="cacheKey"></param>
        /// <param name="create"></param>
        /// <param name="cacheDurationInSeconds"></param>
        /// <returns></returns>
        public V GetOrCreate<V>(string cacheKey, Func<V> create, int cacheDurationInSeconds = int.MaxValue)
        {
            if (this.ContainsKey<V>(cacheKey))
            {
                var result = this.Get<V>(cacheKey);
                if (result == null)
                {
                    return create();
                }
                else
                {
                    return result;
                }
            }
            else
            {
                var result = create();
                this.Add(cacheKey, result, cacheDurationInSeconds);
                return result;
            }
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <typeparam name="V"></typeparam>
        /// <param name="key"></param>
        public void Remove<V>(string key)
        {
            _service.Remove(key);
        }
    }
    //这个类直接复制就行了
}
